package com.zhuoyue.biz.core.api.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuoyue.biz.core.api.dao.AutomateDao;
import com.zhuoyue.biz.core.api.dao.GatewayDao;
import com.zhuoyue.biz.core.api.dao.LocalSceneDao;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.service.AutomateService;
import com.zhuoyue.common.constant.ResultCode;
import com.zhuoyue.common.dto.ResultDTO;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wjming
 * @ClassName: AutomateServiceImpl
 * @Description: 自动化服务
 * @Date 2021-07-01 15:24
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AutomateServiceImpl extends ServiceImpl<AutomateDao, AutomateDO> implements AutomateService {

    private final AutomateDao automateDao;

    private final LocalSceneService localSceneService;

    private final LocalSceneDao localSceneDao;

    private final GatewayDao gatewayDao;
    private static final int HARDWARE_VERSION_NUMBER = 2111;

    @Override
    public List<AutomateDO> getAutomateListByHomeId(String homeId) {
        List<AutomateDO> list = automateDao.selectList(Wrappers.<AutomateDO>lambdaQuery()
                .eq(AutomateDO::getHomeId, homeId));
        for (AutomateDO automateDO : list) {
            String localSceneExDevice = localSceneService.getLocalSceneExDevice(automateDO.getId());
            automateDO.setExecuteDeviceState(localSceneExDevice);
        }

        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    @Override
    public List<AutomateDO> getAutomateListByGatewayMac(String gatewayMac) {
        List<AutomateDO> list = automateDao.selectList(Wrappers.<AutomateDO>lambdaQuery()
                .eq(AutomateDO::getGatewayMac, gatewayMac));
        for (AutomateDO automateDO : list) {
            String localSceneExDevice = localSceneService.getLocalSceneExDevice(automateDO.getId());
            automateDO.setExecuteDeviceState(localSceneExDevice);
        }

        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    /**
     * @Description: 本地场景自动化最多支持100， 但是由于99号是清空指令，所以最大支持98个
     * @param: automate
     * @return: com.zhuoyue.biz.core.api.domain.AutomateDO
     * @author:wjming
     * @Date:2021/4/25 14:56
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutomateDO addAutomate(AutomateDO automate) {


        List<Integer> sceneCode = localSceneDao.selectLocalSceneCodeByGatewayMac(automate.getGatewayMac());
        List<Integer> codeList = automateDao.selectAutomateCodeByGatewayMac(automate.getGatewayMac());
        codeList.addAll(sceneCode);
        GatewayDO gatewayDO = gatewayDao.selectOne(Wrappers.<GatewayDO>lambdaQuery()
                .eq(GatewayDO::getZigbeeMac, automate.getGatewayMac()));
        int countNumber = 46;
        String hardwareVersionNumber = gatewayDO.getHardwareVersionNumber();
        if (StringUtils.isNotEmpty(hardwareVersionNumber) && Integer.parseInt(hardwareVersionNumber) >= HARDWARE_VERSION_NUMBER) {
            countNumber = 98;
        }

        int code = 0;
        if (CollectionUtils.isEmpty(codeList)) {
            code = 1;
        } else {
            if (codeList.size() >= countNumber) {
                throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "本地场景自动化已达上限" + countNumber + "个");
            } else {
                Map<Integer, Integer> map = new HashMap<>(5);
                for (Integer c : codeList) {
                    if (null != c) {
                        map.put(c, c);
                    }
                }
                for (int i = 1; i < countNumber + 1; i++) {
                    if (null == map.get(i)) {
                        code = i;
                        break;
                    }
                }
            }
        }

        if (code < 1 || code > countNumber + 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "本地自动化编号错误！");
        }
        automate.setCode(code);

        int count = automateDao.insert(automate);
        if (count < 1) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "自动化新增失败！");
        }
        localSceneService.sceneOrAuto(automate.getId(), automate.getExecuteDeviceState());

        AutomateDO automateDO = automateDao.selectById(automate.getId());

        String localSceneExDevice = localSceneService.getLocalSceneExDevice(automate.getId());
        automateDO.setExecuteDeviceState(localSceneExDevice);

        if (null == automateDO) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "自动化查询失败！");
        }

        return automateDO;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutomateDO updateAutomateById(AutomateDO automate) {
        int count = automateDao.updateById(automate);
        if (count < 1) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "自动化修改失败!");
        }
        localSceneService.removeSceneAndParam(automate.getId());

        localSceneService.sceneOrAuto(automate.getId(), automate.getExecuteDeviceState());

        AutomateDO automateDO = automateDao.selectById(automate.getId());

        String localSceneExDevice = localSceneService.getLocalSceneExDevice(automate.getId());
        automateDO.setExecuteDeviceState(localSceneExDevice);
        return automateDO;
    }

    @Override
    public void deleteAutomateById(String id) {
        automateDao.deleteById(id);
        localSceneService.removeSceneAndParam(id);
    }


    @Override
    public ResultDTO<AutomateDO> getAutomateById(String id) {
        ResultDTO<AutomateDO> result = new ResultDTO<AutomateDO>();

        try {
            AutomateDO automate = automateDao.selectById(id);
            if (null == automate) {
                result.setSuccess(false);
                result.setResultCode(ResultCode.NO_DATA);
                result.setErrorDetail("该自动化不存在！");
                return result;
            }

            result.setSuccess(true);
            result.setModule(automate);
            result.setResultCode(ResultCode.SUCCESS);
        } catch (Exception e) {
            log.error("AutomateServiceImpl call getAutomateById error ==== ", e);
            result.setSuccess(true);
            result.setResultCode(ResultCode.SYS_ERROR);
            result.setErrorDetail("获取自动化系统异常！");
        }
        return result;
    }


}
